---
title: 使用反射编写泛型数组代码
---
java.lang.reflect 包中的 Array 类允许动态地创建数组。例如，Arrays 类的 copyOf 方法实现中就使用了这个类。这个方法可以扩展一个已经填满的数组。



```java
var a = new Employee[100];

//array is full
a = Arrays.copyOf(a, 2 * a.length);
```

下面使用两种方式尝试实现这样一个通用的方法，方式一是 badCopyOf 方法，因为 Object[] 不能转换成 Employee[] ,所以方式一会报 ClassCastException。

Java 虚拟机会记住每个元素的类型，即创建数组 new 表达式中使用的元素类型。将一个 Employee[] 临时转换为 Object[],然后再把它转换回来是可以的，但一开始就是 Object[] 却永远不能转换成 Employee[]。

为了编写这类通用的数组代码，需要创建与原数组类型相同的新数组。为此，需要使用 java.lang.reflect 包中 Array 类的一些方法。最关键的是 Array 类的静态方法 newInstance。这个方法能够构造一个新数组。在调用这个方法时必须提供两个参数，一个是数组的元素类型，另一个是期望的数组长度。


方式二的 copyof 方法可以用来扩展任意类型的数组，而不仅仅是对象数组
```java title='两种实现方式'
package pub.wkq.java.inheritance.reflection;

import java.lang.reflect.Array;
import java.util.Arrays;

/**
 * @author 王开琦
 */
public class CopyOfTest {
    public static void main(String[] args) {
        int[] a = {1, 2, 3};
        if (goodCopyOf(a, 10) instanceof int[] a1) {
            System.out.println(Arrays.toString(a1));
        }

        String[] b = {"wkq", "zbb", "wkt"};
        if (goodCopyOf(b, 10) instanceof String[] b1) {
            System.out.println(Arrays.toString(b1));
        }
        if (badCopyOf(b, 10) instanceof String[] b1) {
            System.out.println(Arrays.toString(b1));
        }
    }

    public static Object[] badCopyOf(Object[] a, int newLength) {
        var newArray = new Object[newLength];
        System.arraycopy(a, 0, newArray, 0, Math.min(a.length, newLength));
        return newArray;
    }

    /**
     * 1. 首先获得 a 的类对象
     * 2. 确认它确实是一个数组
     * 3. 使用 Class 类的 getComponentType,得到数组的类型
     * 4. 生成新数组
     * @param a
     * @param newLength
     * @return
     */
    public static Object goodCopyOf(Object a, int newLength) {
        Class cl = a.getClass();
        if (!cl.isArray()) {
            return null;
        }
        int length = Array.getLength(a);
        //返回数组的类型
        Class componentType = cl.getComponentType();
        Object newArray = Array.newInstance(componentType, newLength);
        System.arraycopy(a, 0, newArray, 0, Math.min(length, newLength));
        return newArray;
    }
}
```
